package cate.game.role;

import cate.common.game.role.RoleAbstract;
import cate.game.GameBody;
import cate.game.activity.RoleActivity;
import cate.game.activity.RoleActivityGetter;
import cate.game.client.ClientContext;
import cate.game.client.msg.MsgOutput;
import cate.game.framework.ISilenceSpanable;
import cate.game.log.GameLoggerFactory;
import cate.game.play.support.PlayBuildContext;
import cate.game.role.bag.RoleBag;
import cate.game.role.bag.RoleBagGetter;
import cate.game.role.base.RoleBase;
import cate.game.role.base.RoleBaseGetter;
import cate.game.role.chat.RoleChat;
import cate.game.role.chat.RoleChatGetter;
import cate.game.role.farm.RoleFarm;
import cate.game.role.farm.RoleFarmGetter;
import cate.game.role.fight.RoleFight;
import cate.game.role.fight.RoleFightGetter;
import cate.game.role.friend.RoleFriend;
import cate.game.role.friend.RoleFriendGetter;
import cate.game.role.history.RoleHistory;
import cate.game.role.history.RoleHistoryGetter;
import cate.game.role.mail.RoleMail;
import cate.game.role.mail.RoleMailGetter;
import cate.game.role.mall.RoleMall;
import cate.game.role.mall.RoleMallGetter;
import cate.game.role.merge.IRoleMergeSettle;
import cate.game.role.note.RoleNote;
import cate.game.role.note.RoleNoteGetter;
import cate.game.role.pay.RolePay;
import cate.game.role.pay.RolePayGetter;
import cate.game.role.pvp.RolePvp;
import cate.game.role.pvp.RolePvpGetter;
import cate.game.role.res.RoleRes;
import cate.game.role.res.RoleResGetter;
import cate.game.role.show.RoleShow;
import cate.game.role.show.RoleShowGetter;
import cate.game.role.status.RoleStatus;
import cate.game.role.status.RoleStatusGetter;
import cate.game.role.system.RoleSystem;
import cate.game.role.system.RoleSystemGetter;
import cate.game.role.task.RoleTask;
import cate.game.role.task.RoleTaskGetter;
import cate.game.role.trace.RoleTrace;
import cate.game.role.trace.RoleTraceGetter;
import cate.game.role.world.RoleWorld;
import cate.game.role.world.RoleWorldGetter;
import cate.game.role.x.RoleAbstractWriter;
import cate.game.util.ct.CT;
import com.fasterxml.jackson.annotation.JsonIgnore;
import cp.solution.util.time.TimeCostRecord;
import lombok.Getter;
import lombok.Setter;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.springframework.data.annotation.Transient;

import java.util.ArrayList;
import java.util.List;


public class Role implements ISilenceSpanable, IRoleMergeSettle {

    /** 角色唯一ID（数据库入库ID） */
    @Getter
    private final String uid;

    /** 所属游戏上下文 */
    @JsonIgnore
    @Getter
    private transient final GameBody game;

    /** 客户端上下文 */
    @JsonIgnore
    @Getter@Setter
    private transient ClientContext cc;

    @JsonIgnore
    public OperationLog log = new OperationLog();

    @JsonIgnore
    public volatile boolean entering;

    @Transient
    @JsonIgnore
    public transient Logger logger;

    public Role(GameBody game, String uid) {
        this.game = game;
        this.logger = GameLoggerFactory.getLogger(game, Role.class);
        this.uid = uid;
    }

    /** 角色基础数据 */
    private final RoleBaseGetter base = new RoleBaseGetter(this);

    /** 角色身上的【背包】数据 */
    private final RoleBagGetter bag = new RoleBagGetter(this);

    /** 角色身上的【战斗】数据 */
    private final RoleFightGetter fight = new RoleFightGetter(this);

    /** 角色身上的【邮件】数据 */
    private final RoleMailGetter mail = new RoleMailGetter(this);

    /** 角色身上的【好友】 数据 */
    private final RoleFriendGetter friend = new RoleFriendGetter(this);

    /** 角色身上的【商城】 数据 */
    private final RoleMallGetter mall = new RoleMallGetter(this);

    /** 角色身上的【聊天】 数据 */
    private final RoleChatGetter chat = new RoleChatGetter(this);

    /** 角色身上的【支付】 数据 */
    private final RolePayGetter pay = new RolePayGetter(this);

    /** 角色身上的【世界服业务】 数据 */
    private final RoleWorldGetter world = new RoleWorldGetter(this);

    /** 角色身上的【笔记本】 数据 */
    private final RoleNoteGetter note = new RoleNoteGetter(this);

    /** 角色身上的【状态】 数据 */
    private final RoleStatusGetter status = new RoleStatusGetter(this);

    /** 角色身上的【系统】 数据 */
    private final RoleSystemGetter system = new RoleSystemGetter(this);

    /** 角色【资源类玩法】数据 */
    private final RoleResGetter res = new RoleResGetter(this);

    /** 角色【副本类玩法】数据 */
    private final RoleFarmGetter farm = new RoleFarmGetter(this);

    /** 角色身上的【庄园】数据 */
    private final RolePvpGetter pvp = new RolePvpGetter(this);

    /** 角色身上的【活动】数据 */
    private final RoleActivityGetter activity = new RoleActivityGetter(this);

    /** 角色身上的【任务】数据 */
    private final RoleTaskGetter task = new RoleTaskGetter(this);

    /** 角色身上的【历史】数据 */
    private final RoleHistoryGetter history = new RoleHistoryGetter(this);

    /** 角色身上的【展示】数据 */
    private final RoleShowGetter show = new RoleShowGetter(this);

    /** 角色身上的【打点】数据 */
    private final RoleTraceGetter trace = new RoleTraceGetter(this);

    /**
     * 初始化所有模块
     */
    public void initAllPart(){
        this.getBase();
        this.getStatus();
        this.getActivity();
        this.getFarm();
        this.getRes();
        this.getMall();
        this.getBag();
        this.getPay();
        this.getMail();
        this.getChat();
        this.getFriend();
        this.getPvp();
        this.getTask();
        this.getShow();
        this.getTrace();
    }

    public void newAllPart(){
        this.base.getNew();
        this.status.getNew();
        this.activity.getNew();
        this.farm.getNew();
        this.res.getNew();
        this.mall.getNew();
        this.bag.getNew();
        this.pay.getNew();
        this.mail.getNew();
        this.chat.getNew();
        this.friend.getNew();
        this.pvp.getNew();
        this.task.getNew();
        this.show.getNew();
        this.trace.getNew();
    }

    /** 保存到mongodb */
    public void save() {
        this.base.save();
        this.fight.save();
        this.bag.save();
        this.mail.save();
        this.friend.save();
        this.mall.save();
        this.chat.save();
        this.pay.save();
        this.world.save();
        this.status.save();
        this.system.save();
        this.res.save();
        this.farm.save();
        this.pvp.save();
        this.activity.save();
        this.task.save();
        this.history.save();
        this.show.save();
        this.note.save();
        this.trace.save();
    }

    @Override
    public void onDaySpan(boolean silence){
        this.logger.info("玩家{}开始跨天", getBase().name);
        this.getStatus().onDaySpanSafe(silence);
        this.getBag().onDaySpanSafe(silence);
        this.getFight().onDaySpanSafe(silence);
        this.getFarm().onDaySpanSafe(silence);
        this.getPvp().onDaySpanSafe(silence);
        this.getMall().onDaySpanSafe(silence);
        this.getRes().onDaySpanSafe(silence);
        this.getActivity().onDaySpanSafe(silence);
        this.getFriend().onDaySpanSafe(silence);
        this.getTask().onDaySpanSafe(silence);
        this.getPay().onDaySpanSafe(silence);
        this.getSystem().onDaySpanSafe(silence);
        this.getTrace().onDaySpanSafe(silence);
        this.getBase().onDaySpanSafe(silence);
        this.getShow().onDaySpanSafe(silence);
    }

    @Override
    public void onWeekSpan(boolean silence){
        this.logger.info("玩家{}开始跨周", getBase().name);
        this.getStatus().onWeekSpanSafe(silence);
        this.getTask().onWeekSpanSafe(silence);
        this.getFarm().onWeekSpanSafe(silence);
        this.getRes().onWeekSpanSafe(silence);
        this.getMall().onWeekSpanSafe(silence);
        this.getActivity().onWeekSpanSafe(silence);
        this.getPvp().onWeekSpanSafe(silence);
        this.getPay().onWeekSpanSafe(silence);
        this.getFriend().onWeekSpanSafe(silence);
    }

    @Override
    public void onMonthSpan(boolean silence){
        this.logger.info("玩家{}开始跨月", getBase().name);
        this.getStatus().onMonthSpanSafe(silence);
        this.getFarm().onMonthSpanSafe(silence);
        this.getRes().onMonthSpanSafe(silence);
        this.getMall().onMonthSpanSafe(silence);
        this.getActivity().onMonthSpanSafe(silence);
        this.getPvp().onMonthSpanSafe(silence);
        this.getPay().onMonthSpanSafe(silence);
    }

    public void onCreate(){
        this.getBag().onCreate();
        this.getShow().onCreate();
        this.getBase().onCreate();
    }

    /** 发送消息（非实时，性能好） */
    public void send(MsgOutput msg) {
        if(getCc() != null  && !entering){
            this.getCc().send(msg);
            CT.gs(this).nMsgOutput++;
        }
    }

    /** 发送消息（实时，性能差） */
    public void sendNow(MsgOutput msg) {
        if(this.getCc() != null && !entering){
            this.getCc().sendNow(msg);
            CT.gs(this).nMsgOutput++;
        }
    }

    @JsonIgnore
    public RoleBase getBase(){
        return base.get();
    }

    @JsonIgnore
    public RoleBase getBase(boolean createWhenNull){
        return base.get(createWhenNull);
    }

    @JsonIgnore
    public RoleBag getBag(){
        return bag.get();
    }

    @JsonIgnore
    public RoleMail getMail(){
        return mail.get();
    }

    @JsonIgnore
    public RoleFriend getFriend(){
        return friend.get();
    }

    @JsonIgnore
    public RoleFight getFight(){
        return fight.get();
    }

    @JsonIgnore
    public RoleMall getMall(){
        return mall.get();
    }

    @JsonIgnore
    public RoleChat getChat(){
        return chat.get();
    }

    @JsonIgnore
    public RolePay getPay() {
        return pay.get();
    }

    @JsonIgnore
    public RoleWorld getWorld() {
        return world.get();
    }

    @JsonIgnore
    public RoleNote getNote(){
        return note.get();
    }

    @JsonIgnore
    public RoleStatus getStatus(){
        return status.get();
    }

    @JsonIgnore
    public RoleSystem getSystem(){
        return system.get();
    }

    @JsonIgnore
    public RoleRes getRes(){
        return res.get();
    }

    @JsonIgnore
    public RoleFarm getFarm(){
        return farm.get();
    }

    @JsonIgnore
    public RolePvp getPvp(){ return pvp.get(); }

    @JsonIgnore
    public RoleActivity getActivity(){return activity.get();}

    @JsonIgnore
    public RoleTask getTask(){return task.get();}

    @JsonIgnore
    public RoleHistory getHistory(){return history.get();}

    @JsonIgnore
    public RoleShow getShow(){return show.get();}

    @JsonIgnore
    public RoleTrace getTrace() {
        return trace.get();
    }

    @Override
    public String toString() {
        return "Role{"+uid+"|"+getBase().name+"}";
    }

    public String coverInfo() {
        StringBuilder sb = new StringBuilder();
        RolePartGetter[] parts = new RolePartGetter[] {
                base,fight,bag,mail,friend,mall,chat,pay,world,status,
                system,res,farm,pvp,activity,task,history,show,note, trace
        };
        List<String> used = new ArrayList<>();
        List<String> noUsed = new ArrayList<>();
        for(RolePartGetter part : parts) {
            if(null != part.get(false)) {
                used.add(part.getClass().getName());
            } else {
                noUsed.add(part.getClass().getName());
            }
        }
        sb.append("used="+used.size());
        sb.append(" noUsed="+noUsed.size());
        sb.append(" used=" + StringUtils.join(used, ","));
        sb.append(" noUsed=" + StringUtils.join(noUsed, ","));
        return sb.toString();
    }

    /** 合服结算时 */
    @Override
    public void onMergeSettle(GameBody game, TimeCostRecord tcr) {
        // 推荐利用tcr细分记录各操作耗时，以更好追溯潜在问题
        tcr.start("base标记");
        this.getBase().uni.traversalLog = "play-demo";
        tcr.stop("base标记");

        tcr.start("farm");
        this.getFarm().onMergeSettle(game, tcr);
        tcr.stop("farm");

        tcr.start("pvp");
        this.getPvp().onMergeSettle(game, tcr);
        tcr.stop("pvp");

        tcr.start("activity");
        this.getActivity().onMergeSettle(game, tcr);
        tcr.stop("activity");
    }

    public PlayBuildContext toPlayBuildContext() {
        return getGame().fight.getPlayBuildContext();
    }

    /** 转化为角色摘要 */
    public RoleAbstract toAbstract() {
        return RoleAbstractWriter.create(this);
    }
}
